﻿using System.Collections.Generic;
using System.IO;
using Super_Management_Mayhem.Content.Spritesheet;
using Transformable_Engine_v2.Engine.Animation.PositionAnimation;
using Transformable_Engine_v2.Engine.Animation.Trajectory;
using Transformable_Engine_v2.Engine.GameObjects.Containers;
using Transformable_Engine_v2.Engine.GameObjects.Primitives;
using Transformable_Engine_v2.Engine.Graphics;
using Transformable_Engine_v2.Engine.Time;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Super_Management_Mayhem.Screens.Menu.SelectAvatar
{
    public class SelectAvatarMenu : BaseMenuScreen<MainMenu.Menu>
    {
        private readonly ImageContainer _spotlight;
        private readonly RectanglePrimitive _darkness;

        private List<ProfileData> _profiles;

        private Avatar _enteringPlayer;
        private Avatar _leavingPlayer;

        private readonly TE_Vector2 _hudSize;
        private readonly Container _playerContainer;

        private int _selectedIndex;

        private const int ANIMATION_TIME = 1000;
        private readonly Timer _animationTimer;

        private EmployeeCard _oldEmployeeCard;
        private EmployeeCard _newEmployeeCard;

        private readonly Container _employeeCardContainer;

        private Container _leftArrow;
        private Container _rightArrow;

        public SelectAvatarMenu(TE_Vector2 size)
        {
            LoadProfiles();

            _hudSize = size;
            _selectedIndex = 0;

            _animationTimer = new Timer(ANIMATION_TIME, false, EndPlayerEnter);
            AddTimers(_animationTimer);

            _spotlight = new ImageContainer {
                                                PositionGridBound = new TE_Vector2(0, 3),
                                                Sprite = MenuSheet.GetSprite(MenuSheet.Menu.SpotLight),
                                                Scale = new TE_Vector2(3, 3)
                                            };

            _darkness = new RectanglePrimitive {
                                                   Shape = new TE_Rectangle(0, 0, size),
                                                   FillColor = new Color(Color.Black, 0)
                                               };

            _leftArrow = new ImageContainer {
                                                PositionGridBound = new TE_Vector2(1, 23),
                                                Sprite = MenuSheet.GetSprite(MenuSheet.Menu.Arrow),
                                                Mirror = ImageContainer.MirrorState.MirrorHorizontal,
                                                Visible = false
                                            };
            _leftArrow.AddAnimations(new PositionAnimation(new SinusTrajectory(), new TE_Vector2(0.5f, 23), 1000, true, 0));
            _rightArrow = new ImageContainer {
                                                 PositionGridBound = new TE_Vector2(15, 23),
                                                 Sprite = MenuSheet.GetSprite(MenuSheet.Menu.Arrow),
                                                 Visible = _profiles.Count > 0
                                             };
            _rightArrow.AddAnimations(new PositionAnimation(new SinusTrajectory(), new TE_Vector2(15.5f, 23), 1000, true, 0));

            var title = Title.Blue("Select a character", size);

            _playerContainer = new Container(9, 25);

            _employeeCardContainer = new Container(size.Y - 10, 6);

            AddChildren(_spotlight, _playerContainer, _employeeCardContainer, _darkness, title, _leftArrow, _rightArrow);

            _enteringPlayer = new Avatar();
            _playerContainer.AddChildren(_enteringPlayer);

            _newEmployeeCard = new EmployeeCard();
            _employeeCardContainer.AddChildren(_newEmployeeCard);

            LetThereBeLight();
        }

        public ProfileData Profile
        {
            get
            {
                if(_selectedIndex == 0)
                    return null;

                return _profiles[_selectedIndex - 1];
            }
        }

        void LoadProfiles()
        {
            _profiles = new List<ProfileData>();

            if (!Directory.Exists("Content/Config/Profiles"))
                Directory.CreateDirectory("Content/Config/Profiles");

            var profilesFolder = Directory.GetFiles("Content/Config/Profiles", "*.profile");

            foreach (var profilePath in profilesFolder)
            {
                _profiles.Add(ProfileData.FromFile(profilePath));
            }
        }

        void PlayerEnter(TE_Vector2 startPosition)
        {
            _leftArrow.Visible = false;
            _rightArrow.Visible = false;

            CastDarkness();
            _leavingPlayer = _enteringPlayer;
            
            if(startPosition.X > 0)
                _leavingPlayer.WalkAnimationLeft();
            else
                _leavingPlayer.WalkAnimationRight();
            
            _leavingPlayer.AddAnimations(new PositionAnimation(new LinearEasing(), -startPosition, ANIMATION_TIME, false, 0));
            _leavingPlayer.Die(ANIMATION_TIME);

            
            if(_selectedIndex == 0)
            {
                _enteringPlayer = new Avatar {
                                                 PositionGridBound = startPosition
                                             };
            }
            else
            {
                _enteringPlayer = new Avatar(_profiles[_selectedIndex - 1].GetColor()) {
                                                            PositionGridBound = startPosition
                                                        };
            }

            //For some reason, the shader will not work if the _enteringPlayer is the latest children
            var dummy = new Avatar {Visible = false};
            dummy.Die();

            if(startPosition.X > 0)
                _enteringPlayer.WalkAnimationLeft();
            else
                _enteringPlayer.WalkAnimationRight();
            
            _enteringPlayer.AddAnimations(new PositionAnimation(new LinearEasing(), TE_Vector2.Zero, ANIMATION_TIME, false, 0));
            _playerContainer.AddChildren(_enteringPlayer, dummy);

            _animationTimer.Start();

            SwitchCards(startPosition);
        }

        void SwitchCards(TE_Vector2 startPosition)
        {
            _oldEmployeeCard = _newEmployeeCard;

            _oldEmployeeCard.AddAnimations(new PositionAnimation(new LinearEasing(), -startPosition, ANIMATION_TIME, false, 0));
            _oldEmployeeCard.Die(ANIMATION_TIME);

            if(_selectedIndex > 0)
                _newEmployeeCard = new EmployeeCard(_profiles[_selectedIndex - 1]);
            else
            {
                _newEmployeeCard = new EmployeeCard();
            }
            _newEmployeeCard.PositionGridBound = new TE_Vector2(_hudSize.X / 2 + 2, 0);
            _newEmployeeCard.AddAnimations(new PositionAnimation(new QuadraticEasing(BaseTrajectory.Easing.EaseOut), TE_Vector2.Zero, ANIMATION_TIME / 2, false, ANIMATION_TIME));

            _employeeCardContainer.AddChildren(_newEmployeeCard);
        }

        void EndPlayerEnter()
        {
            _enteringPlayer.Stop();
            LetThereBeLight();

            if(_selectedIndex == 0)
                _rightArrow.Visible = true;
            else if(_selectedIndex == _profiles.Count)
                _leftArrow.Visible = true;
            else
            {
                _leftArrow.Visible = true;
                _rightArrow.Visible = true;
            }
        }

        void LetThereBeLight()
        {
            _spotlight.Visible = true;
            _darkness.Visible = false;
        }

        void CastDarkness()
        {
            _spotlight.Visible = false;
            _darkness.Visible = true;
        }

        public override void UpKey(int id)
        {
            
        }

        public override void DownKey(int id)
        {

        }

        public override void LeftKey(int id)
        {
            if(!_animationTimer.IsStarted && _selectedIndex > 0)
            {
                _selectedIndex--;
                PlayerEnter(new TE_Vector2(-_hudSize.X, 0));
            }
        }

        public override void RightKey(int id)
        {
            if(!_animationTimer.IsStarted && _selectedIndex < _profiles.Count)
            {
                _selectedIndex++;
                PlayerEnter(new TE_Vector2(_hudSize.X, 0));
            }
        }

        public override void AcceptKey(int id)
        {
            if(_selectedIndex == 0)
            {
                ChangeScreen(-1, MainMenu.Menu.CreateNewAvatar_Name);
            }
            else
            {
                ChangeScreen(-1, MainMenu.Menu.Waiting);
            }
        }

        public override void CancelKey(int id)
        {

        }
    }
}